home *** CD-ROM | disk | FTP | other *** search
/ SuperHack / SuperHack CD.bin / CODING / PASCAL / ALLSWAGS.ZIP / SWAGG-M.ZIP / MISC.SWG / 0159_AI Game Playing.pas < prev    next >
Encoding:
Pascal/Delphi Source File  |  1995-09-04  |  19.1 KB  |  738 lines

  1. {$IFDEF DEBUG}
  2. {$A+,B-,D+,F-,G-,I-,K-,L-,N-,E-,P-,Q+,R+,S+,T-,V-,W+,X+,Y-}
  3. {$ELSE}
  4. {$A+,B-,D-,F-,G-,I-,K-,L-,N-,E-,P-,Q-,R-,S-,T-,V-,W+,X+,Y-}
  5. {$ENDIf}
  6.  
  7. {************************************************}
  8. {                                                }
  9. {   SNAiL ViSiON Demo  v1.00.00                  }
  10. {   Strange Logic Software <=> Brad Zavitsky     }
  11. {   All Rights Reserved (1995)                   }
  12. {                                                }
  13. {************************************************}
  14.  
  15. {
  16.  | NOTES:
  17.  \-------
  18.  
  19.   There are no known bugs.
  20.  
  21.   Some people have been wondering about computer games so-called AI,
  22.   this is a demo of PAI (Psuedo Artificial Inteligence <g>)
  23.  
  24.   Sorry, no graphics :-), this is just ascii.
  25.  
  26.   I have made most of the games settings constants for changing various
  27.   things around.
  28.  
  29.   If compiling in G+ mode, change COMPSPEED accordingly the enemies
  30.   go MUCH faster.
  31.  
  32.   This will even work on a 8088 in REAL TIME! It has been pretty optimized
  33.   for speed and size, notice, it does not use any units, cut back in a
  34.   ton of linking.
  35.  
  36.   SWAG use it allowed (that is really the goal)
  37.  
  38. VERSIONS --
  39.    1.00.00 : First public release. Since I first posted this in the
  40.              PASCAL LESSONS confrence I have made MANY changes to make
  41.              it more of a game/run faster/ and have more configurable
  42.              settings.  Est.. *OPERATING Speed is 200%-500% faster.
  43.  
  44.   * I do have a delay which slows things down to regulate speeds.
  45.  
  46. }
  47.  
  48. Program Snaildemo;
  49. {$M $400,0,0}
  50.  
  51.  
  52. Const
  53.  Top       = 3;  {Specs of your screen -2/+2}
  54.  Bottom    = 22; {""}
  55.  RtSide    = 77; {""}
  56.  LftSide   = 3;  {""}
  57.  
  58.  Version        : string[7] = '1.00.00';
  59.  CompSpeed      : word = 6; {Higher = easier|Even = Easier}
  60.  MaxEnemy              = 68;  {Should greater or equal to NumEnemy}
  61.  NumEnemy       : word = 30;  {Number of enemies}
  62.  AI             : Byte = 60; {random move chance}
  63.  Rep            : Byte = 3;  {Energy replenish}
  64.  JumpChance     : Byte = 90; {chance to make a jump}
  65.  BadScore       : Integer = -5;  {Happens when a jump is failed}
  66.  BadEnergy      : Integer = -75; {Happens after a jump is failed}
  67.  MaxEnergy      : Word = 5000; {Max amount of energy}
  68.  MaxScore       : Word = 65500;
  69.  Drain          : Word = 2;    {Amount drained per keypress}
  70.  StartingEnergy : Word = 200;  {Amount of starting energy}
  71.  Scost          : Word = 2; {Shield Usage Cost, if half}
  72.                             {then energy wont go down unless moving}
  73.  SNeed          : Word = 10; {Energy needed mantain shields}
  74.  StatUpDate     : Byte = 5; {When to update stats}
  75.  ENeed          : Word = 2; {Energy needed to move}
  76.  JNeed          : Word = 100; {Energy needed for hyper jump}
  77.  SnailMan   : Char = '@'; {Our hero}
  78.  Langolier  : Char = '#'; {Bad Guys}
  79.  SoundOn    : Boolean = True; {Turn this off if you don't like noise}
  80.  
  81. Type
  82.      {Directions used by MOVE}
  83.      Dirtype = (North, East, West, South);
  84.  
  85.      {These are actually player/enemy records, you could probally
  86.      add such things as hitpoints pretty easily}
  87.      CursorRec = Record
  88.                  X,Y:Byte;
  89.                  End;
  90.  
  91.     { All the possible enemies, I have personally gone up
  92.       to 1000 w/out changing memory! }
  93.      AllEnemy = array[1..MaxEnemy] of CursorRec;
  94.  
  95.  
  96. Var
  97.     Dead   : Boolean; {Gee...what could this mean}
  98.     Round, {Used to regulate stats updates}
  99.     Turn   : Byte; {This regulates enemy movement}
  100.     Temp   : AllEnemy; {BadGuy location, just what snailman needs to avoid}
  101.     Loc    : CursorRec; {Snailmans Location}
  102.     I      : Integer; {All purpose integer}
  103.     Len    : Byte; {Stores length of previous string for status line}
  104.     Score, { player score}
  105.     Energy : integer; {players current energy}
  106.     OneMs  : Word; {Used by delays, DO NOT TOUCH <g>}
  107.     Ch     : Char; {IO char}
  108.     ShieldOn : Boolean; {True if shields are on}
  109.     PlayAnother : Boolean; {Play another game?}
  110.  
  111.  
  112. Procedure CB;Inline($CD/$33); {Simulate a ^C}
  113.  
  114. Procedure DelayOneMS; assembler; {Better delay for 1ms}
  115.   asm
  116.      PUSH CX         { Save CX }
  117.      MOV  CX, OneMS  { Loop count into CX }
  118.   @1:
  119.      LOOP @1         { Wait one millisecond }
  120.      POP  CX         { Restore CX }
  121.   end;
  122.  
  123. Procedure Delay(ms:Word); assembler; {better delay}
  124.   asm
  125.      MOV  CX, ms
  126.      JCXZ @2
  127.   @1:
  128.      CALL DelayOneMS
  129.      LOOP @1
  130.   @2:
  131.   end;
  132.  
  133. Procedure Calibrate_Delay; assembler; {makes delay accurate}
  134.   asm
  135.      MOV  AX,40h
  136.      MOV  ES,AX
  137.      MOV  DI,6Ch          { ES:DI is the low word of BIOS timer count }
  138.      MOV  OneMS,55        { Initial value for One MS's time }
  139.      XOR  DX,DX           { DX = 0 }
  140.      MOV  AX,ES:[DI]      { AX = low word of timer }
  141.   @1:
  142.      CMP  AX,ES:[DI]      { Keep looking at low word of timer }
  143.      JE   @1              { until its value changes... }
  144.      MOV  AX,ES:[DI]      { ...then save it }
  145.   @2:
  146.      CAll DelayOneMs      { Delay for a count of OneMS (55) }
  147.      INC  DX              { Increment loop counter }
  148.      CMP  AX,ES:[DI]      { Keep looping until the low word }
  149.      JE   @2              { of the timer count changes again }
  150.      MOV  OneMS, DX       { DX has new OneMS }
  151.   end;
  152.  
  153. Procedure Beep(Hz, MS:Word); assembler;
  154.      { Make the Sound at Frequency Hz for MS milliseconds }
  155.   ASM
  156.     MOV  BX,Hz
  157.     MOV  AX,34DDH
  158.     MOV  DX,0012H
  159.     CMP  DX,BX
  160.     JNC  @Stop
  161.     DIV  BX
  162.     MOV  BX,AX
  163.     IN          AL,61H
  164.     TEST AL,3
  165.     JNZ  @99
  166.     OR          AL,3
  167.     OUT  61H,AL
  168.     MOV  AL,0B6H
  169.     OUT  43H,AL
  170.  @99:
  171.     MOV  AL,BL
  172.     OUT  42H,AL
  173.     MOV  AL,BH
  174.     OUT  42H,AL
  175.  @Stop:
  176.  {$IFOPT G+}
  177.     PUSH MS
  178.  {$ELSE }
  179.     MOV  AX, MS   { push delay time }
  180.     PUSH AX
  181.   {$ENDIF }
  182.     CALL Delay    { and wait... }
  183.  
  184.     IN   AL, $61  { Now turn off the speaker }
  185.     AND  AL, $FC
  186.     OUT  $61, AL
  187.   end;
  188.  
  189. Procedure BoundsBeep; assembler; {Means you are touching an enemy}
  190.   asm
  191.   {$IFOPT G+ }
  192.      PUSH 1234      { Pass the Frequency }
  193.      PUSH 10        { Pass the delay time }
  194.   {$ELSE}
  195.      MOV  AX, 1234  { Pass the Frequency }
  196.      PUSH AX
  197.      MOV  AX, 10    { Pass the delay time }
  198.      PUSH AX
  199.    {$ENDIF }
  200.      CALL Beep
  201.   end;
  202.  
  203. Procedure ErrorBeep; assembler;{Means you have touched an enemy and died}
  204.   asm
  205.   {$IFOPT G+ }
  206.      PUSH 800   { Pass the Frequency }
  207.      PUSH 75    { Pass the delay time }
  208.   {$ELSE}
  209.      MOV  AX, 800  { Pass the Frequency }
  210.      PUSH AX
  211.      MOV  AX, 75   { Pass the delay time }
  212.      PUSH AX
  213.   {$ENDIF }
  214.      CALL Beep
  215.   end;
  216.  
  217. Procedure AttentionBeep; assembler; {Status Update beep}
  218.   asm
  219.   {$IFOPT G+ }
  220.      PUSH 660   { Pass the Frequency }
  221.      PUSH 50    { Pass the delay time }
  222.   {$ELSE}
  223.      MOV  AX, 660  { Pass the Frequency }
  224.      PUSH AX
  225.      MOV  AX, 50   { Pass the delay time }
  226.      PUSH AX
  227.   {$ENDIF }
  228.      CALL Beep
  229.   end;
  230.  
  231.  
  232.  
  233. Procedure WarpSound; {Attemped warp sound}
  234.  Var I:Word;
  235.   Begin
  236.     For I:= 500 to 600 do Beep(I,10);
  237.   End;
  238.  
  239. Procedure WarpDown; {Completed warp sound}
  240.  Var I:Word;
  241.   Begin
  242.     For I:= 600 downto 500 do Beep(I,10);
  243.     Delay(200);
  244.     Beep(1000,10);
  245.     Delay(200);
  246.     Beep(1000,10);
  247.   End;
  248.  
  249.  
  250. Procedure FClr;Assembler; {ClrScr}
  251.   Asm
  252.    MOV AH,0Fh
  253.    Int 10h
  254.    MOV AH,0
  255.    Int 10h
  256.   End;
  257.  
  258. Procedure GotoXY(X,Y : Byte); Assembler;
  259. Asm
  260.   MOV DH, Y    { DH = Row (Y) }
  261.   MOV DL, X    { DL = Column (X) }
  262.   DEC DH       { Adjust For Zero-based Bios routines }
  263.   DEC DL       { Turbo Crt.GotoXY is 1-based }
  264.   MOV BH,0     { Display page 0 }
  265.   MOV AH,2     { Call For SET CURSOR POSITION }
  266.   INT 10h
  267. end;
  268.  
  269. Function Int2Str(Number : LongInt): String;
  270. Var
  271. Temp : String[64];
  272. Begin
  273.    Str(Number,Temp);
  274.    Int2Str := Temp;
  275. End;
  276.  
  277. Procedure SetXY(x,y:byte;var A:CursorRec);
  278.  Begin
  279.   If (X > 0) and (X < 80) then A.x := x;
  280.   If (Y > 0) and (Y < 25) then A.y := y;
  281.  End;
  282.  
  283. Procedure ClearKeyBoard;{Fast key clearer}
  284. Begin
  285.  ASM CLI End;
  286.  MemW[$40:$1A] := MemW[$40:$1C];
  287.  ASM STI End;
  288. End;
  289.  
  290. Procedure GoXY(A:CursorRec); {moves cursorrec to its position}
  291.  Begin
  292.   Gotoxy(a.x,a.y);
  293.  End;
  294.  
  295. Procedure HideCursor; Assembler;
  296. Asm
  297.   MOV   ax,$0100
  298.   MOV   cx,$2607
  299.   INT   $10
  300. end;
  301.  
  302. Procedure ShowCursor; Assembler;
  303. Asm
  304.   MOV   ax,$0100
  305.   MOV   cx,$0506
  306.   INT   $10
  307. end;
  308.  
  309. Function WhereX : Byte;  Assembler;
  310. Asm
  311.   MOV     AH,3      {Ask For current cursor position}
  312.   MOV     BH,0      { On page 0 }
  313.   INT     10h       { Return inFormation in DX }
  314.   INC     DL        { Bios Assumes Zero-based. Crt.WhereX Uses 1 based }
  315.   MOV     AL, DL    { Return X position in AL For use in Byte Result }
  316. end;
  317.  
  318. Function WhereY : Byte; Assembler;
  319. Asm
  320.   MOV     AH,3     {Ask For current cursor position}
  321.   MOV     BH,0     { On page 0 }
  322.   INT     10h      { Return inFormation in DX }
  323.   INC     DH       { Bios Assumes Zero-based. Crt.WhereY Uses 1 based }
  324.   MOV     AL, DH   { Return Y position in AL For use in Byte Result }
  325. end;
  326.  
  327. Procedure GETXY(A:CursorRec); {set cursorrec}
  328.  Begin
  329.   A.x := WhereX;
  330.   A.y := WhereY;
  331.  End;
  332.  
  333. Procedure StatusBeep; {Look up, status line has been updated}
  334.  Begin
  335.   AttentionBeep;
  336.   Delay(50);
  337.   AttentionBeep;
  338.  End;
  339.  
  340.  
  341. Function Readkey:char;Inline($B4/$07/$CD/$21);
  342.  
  343. function KeyPressed:boolean;assembler;
  344.  asm
  345.  mov ah,$B;
  346.  int $21;
  347.  and al,$FE;
  348. end;
  349.  
  350. Procedure ClrBox(X1,Y1,X2,Y2:Byte);
  351.  Var
  352.    OldX :Byte; AnyBt:Byte;
  353.    OldY :Byte; AnyBt2:Byte;
  354.  
  355.  Begin
  356.   OldX := WhereX;
  357.   OldY := WhereY;
  358.   gotoxy(x1,y1);
  359.   For Anybt :=1 to Y2 do begin
  360.    For AnyBt2 :=1 to X2 do write(#0);
  361.    gotoxy(X1,Y1+AnyBt);
  362.   End{For Loop};
  363.   gotoxy(oldX,OldY);
  364.   End;
  365.  
  366. Procedure Status(S:String;Clear:Boolean;UseSound:Boolean);
  367. {Gives messages on first line}
  368.  Begin
  369.  If (Clear) and (SoundOn) and (UseSound) then StatusBeep;
  370.  Gotoxy(1,1);
  371.  If Clear then ClrBox(1,1,Len,1) else gotoxy(len,1);
  372.  Write(S);
  373.  If Clear then Len:= Length(S) else Len:= Len + Length(S)+1;
  374.  inc(len);
  375.  Goxy(Loc);
  376.  End;
  377.  
  378. Function P100(Percent:Word):Boolean;  {Percentage 100}
  379.   Begin
  380.    P100 := False;
  381.    If Random(100)+1 <= Percent then P100 := True;
  382.   End;
  383.  
  384. Procedure StatInit; {Set up status bar |not status line|}
  385. Begin
  386. gotoxy(1,2);
  387. Write('[ STATUS ]   ENERGY:            SHIELDS:            SCORE:');
  388. End;
  389.  
  390. {The following procedure update the status bar}
  391.  
  392. Procedure UpDateEnergy;
  393.  Var i:Byte;
  394.  Begin
  395.  Gotoxy(21,2);
  396.  For I:=1 to 5 do write(#32);
  397.  Gotoxy(21,2);
  398.  Write(Energy);
  399.  Goxy(Loc);
  400.  End;
  401.  
  402. Procedure UpDateShields;
  403.  Var i:Byte;
  404.  Begin
  405.  StatusBeep;
  406.  Gotoxy(41,2);
  407.  For I:=1 to 5 do write(#32);
  408.  Gotoxy(41,2);
  409.  Write(ShieldOn);
  410.  Goxy(Loc);
  411.  End;
  412.  
  413. Procedure UpDateScore;
  414.  Var i:Byte;
  415.  Begin
  416.  Gotoxy(59,2);
  417.  For I:=1 to Length(int2str(Energy))+2 do write(#32);
  418.  gotoxy(59,2);
  419.  Write(Score);
  420.  Goxy(Loc);
  421.  End;
  422.  
  423. Procedure EngageShields; {Change shield status}
  424. Begin
  425.  ShieldOn := not ShieldOn;
  426.  UpDateShields;
  427. End;
  428.  
  429. procedure Firephasers(A:CursorRec); {Check for collisions}
  430.      begin
  431.        If (A.x = Loc.x) and (A.Y = Loc.Y) then
  432.        begin
  433.         BoundsBeep;
  434.         GoXy(A);
  435.         Write(Langolier);
  436.         If not shieldOn then
  437.         begin
  438.          If SoundOn then ErrorBeep;
  439.          Dead := True;
  440.         End;{ShieldOn}
  441.       end;{If Locs match}
  442.      End;{Fire}
  443.  
  444. Procedure CheckHits;  {Check for collisions}
  445.  Var I:word;
  446.   Begin
  447.    While not dead and (I <> NumEnemy) do
  448.     For I:= 1 to NumEnemy do Firephasers(Temp[I]);
  449.   End;
  450.  
  451. Function Move(Dir:DirType;Var A:CursorRec;Ch:Char):Boolean;
  452. {Move player/enemies}
  453.  Begin
  454.  Move := True;
  455.  Case Dir of
  456.   North: Begin
  457.            If A.Y <= top then Move := False else
  458.            begin
  459.             goxy(A);
  460.             Write(#0);
  461.             Dec(A.Y);
  462.             GoXY(A);
  463.             Write(Ch);
  464.            End;{If wherey}
  465.            End;{K_Up}
  466.  
  467.   South: Begin
  468.          If A.Y >= bottom then Move := False else
  469.           begin
  470.           goxy(A);
  471.           Write(#0);
  472.           Inc(A.Y);
  473.           GoXY(A);
  474.           Write(ch);
  475.           End;{If wherey}
  476.           End;{K_Down}
  477.  
  478.   East: Begin
  479.            If A.X >= rtside then Move := False else
  480.            begin
  481.             goxy(A);
  482.             Write(#0);
  483.             Inc(A.X);
  484.             GoXY(A);
  485.             Write(Ch);
  486.             End;{If wherex}
  487.             End;{K_Right}
  488.  
  489.   West: Begin
  490.          If A.X <= lftside then Move := False else
  491.           begin
  492.           goxy(A);
  493.           write(#0);
  494.           Dec(A.X);
  495.           GoXY(A);
  496.           Write(Ch);
  497.           End;{If wherex}
  498.           End;{K_Left}
  499.  
  500.  End;{Case}
  501.  CheckHits;
  502.  End;{Move}
  503.  
  504. Procedure Jump; {Hyper Jump}
  505.  Begin
  506.   Status('Attempting Jump...',True,False);
  507.   If SoundOn then WarpSound;
  508.   If Energy >= Jneed then
  509.   begin
  510.   If P100(JumpChance) then {If you don't fail...}
  511.   begin
  512.    Goxy(Loc);
  513.    Write(#0);
  514.    SetXy((random(rtside-lftside)+lftside+1),(random(bottom-top)+top+1)
  515.    ,Loc);
  516.    goxy(Loc);
  517.    Write(snailman);
  518.    Dec(Energy, Jneed); {Get rid of used energy}
  519.    Status('successfull',false,True);
  520.    If SoundOn then WarpDown; {make some noise}
  521.   End Else
  522.    Begin
  523.    Delay(200);    {Failed Warp Noise}
  524.    Beep(1500,20);
  525.    Delay(200);
  526.    Beep(1500,20);
  527.    Delay(200);
  528.    Beep(1500,20);
  529.    Delay(200);
  530.    Beep(1500,20);
  531.    Status('Failed',False,True);
  532.    Energy := BadEnergy; {Pay the price of a blown engine}
  533.    Score := BadScore;   {""}
  534.    End;
  535.   End else Begin
  536.     status('not enough energy!',false,True);
  537.     Delay(200);
  538.     Beep(1000,10);
  539.    End;
  540.  End;
  541.  
  542. procedure Movefoes; {The enemy is on the move}
  543.      Var I:Word;
  544.      begin
  545.      Turn := 0; {reset turns}
  546.      For I:=1 to numenemy do
  547.      Begin
  548.  
  549.      If Temp[I].X > Loc.X then Move(West,Temp[I],langolier) else
  550.      If Temp[I].X < Loc.X then Move(East,Temp[I],langolier);
  551.  
  552.      If Temp[I].Y > Loc.Y then Move(North,Temp[I],langolier) else
  553.      If Temp[I].Y < Loc.Y then Move(South,Temp[I],langolier);
  554.  
  555.  
  556.      If P100(AI) then {do they move on their own?}
  557.      begin
  558.       case (random(4)+1) of
  559.        1: Move(North,Temp[I],langolier);
  560.        2: Move(South,Temp[I],langolier);
  561.        3: Move(West,Temp[I],langolier);
  562.        4: Move(East,Temp[I],langolier);
  563.        End;{Case}
  564.       End;{Begin}
  565.      end;{for to do}
  566.      {EnemySave;}
  567.      end;
  568.  
  569. procedure Addscore; {regulates energy use, this could use some work}
  570.  begin
  571.    if (energy < MaxEnergy) and (odd(turn)) then inc(energy,rep);
  572.    if (score < MaxScore) and (turn = compspeed-1) then inc(score);
  573.   end;
  574.  
  575.  
  576. procedure Playgame; {Let the games begin}
  577.      Var i:Word;
  578.      begin
  579.      For I:=1 to numenemy do {set up starting positions}
  580.      begin
  581.      SetXy((random(rtside-lftside)+lftside+1),(random(bottom-top)+top+1)
  582.            ,Temp[I]);
  583.      goxy(Temp[I]);
  584.      Write(langolier);
  585.      end;
  586.  
  587.      SetXy(3,5,Loc);
  588.      goxy(loc);
  589.      Write(snailman);
  590.      repeat {begin}
  591.         While keypressed do {MUCH faster than "If Keyressed"}
  592.            Begin
  593.             Ch := readkey;
  594.             If (CH = #0) and (ENergy > ENeed) then
  595.           {a function key means they are moving}
  596.             BEGIN
  597.             Dec(Energy, Drain);
  598.             Ch := Readkey;
  599.             Case CH of
  600.    { left }   #75 : Move(West,Loc,snailman);
  601.    { rite }   #77 : Move(East,Loc,snailman);
  602.    {  Up  }   #72 : Move(North, Loc, snailman);
  603.    { Down }   #80 : Move(South, Loc,snailman);
  604.    { PGup }   #73 : Begin
  605.                      Move(North, Loc, snailman);
  606.                      Move(East,Loc,snailman);
  607.                     End;
  608.  
  609.    { PDdn }   #81 : Begin
  610.                      Move(South, Loc,snailman);
  611.                      Move(East,Loc,snailman);
  612.                     End;
  613.  
  614.    { Home }   #71 : Begin
  615.                      Move(North, Loc, snailman);
  616.                      Move(West,Loc,snailman);
  617.                     End;
  618.  
  619.    { End  }   #79 : Begin
  620.                      Move(South, Loc, snailman);
  621.                      Move(West,Loc,snailman);
  622.                     End;
  623.  
  624.             End;{Case}
  625.             END ELSE
  626.             Case Ch of
  627.            'Q','q' : Dead := True;{Quit}
  628.            'J','j' : Jump;  {Jump}
  629.            'S','s' : EngageShields;{Engage/disEngage shields}
  630.            'P','p' : Begin
  631.                      Inc(Energy, Drain); {Reimburse energy}
  632.                      Status('Paused... press <ENTER>',true,True);
  633.                      repeat until readkey = #13;
  634.                      Status('',True,True);
  635.                      End;
  636.  
  637.                #3 :  CB;  {^C}
  638.            End;{case}
  639.            End;{While}
  640.  
  641.           If (Energy < SNeed) and (ShieldOn) then
  642.            Begin
  643.             ShieldOn := False;
  644.             UpDateShields;
  645.            End;
  646.  
  647.           If ShieldOn then Dec(Energy, SCost);
  648.           ClearKeyBoard;
  649.  
  650.           If Round = StatUpDate then
  651.            Begin
  652.             GoXy(Loc);
  653.             Write(SnailMan);
  654.             UpDateEnergy;
  655.             UpDateScore;
  656.             Round := 0;
  657.            End;
  658.           inc(Round);
  659.  
  660.           If turn >= compspeed then movefoes;
  661.           inc(turn);
  662.  
  663.           addscore;
  664.           Delay(100);
  665.           {end} until dead;
  666.      end;
  667.  
  668. Procedure SayHi; {Internal Instructions}
  669. Begin
  670. Writeln('Welcome to SNAiL ViSiON -- The virtual snail network -- ');
  671. Writeln('and only on channel 3031.  Tonight we bring you, once again,');
  672. Writeln('SNAiL MAN!  Can the not-so-brave-and-not-too-tough SNAiLMAN');
  673. Writeln('save the day?  Well, as you know, with ViRTUAL SNAiL REALiTY');
  674. Writeln('you will decide.  And just how do you win you ask?  Well the');
  675. Writeln('snail isn''t known for it''s ninja-like karate skills, so');
  676. Writeln('you just have to run as only a snail can.');
  677. Writeln('');
  678. Writeln('Advice --');
  679. Writeln(' When you here two beeps, look up, it means something has');
  680. Writeln(' just been updated.  Also, be carefull when using');
  681. Writeln(' HyperJump,if you fail you loose energy and points');
  682. Writeln('');
  683. Writeln('Instructions --');
  684. Writeln(' Arrow keys move you in corresponding directions.');
  685. Writeln(' PgUp, PgDn, Home, and End move diagonaly.');
  686. Writeln(' P - Pause   Q - Commit Sucicide   S - Engage Snail Shields');
  687. Writeln(' J - Snail HyperJump!');
  688. Writeln('');
  689. Writeln('Symbols --');
  690. Writeln(' ',SnailMan,' - Snailman   ',Langolier,' - Langolier');
  691. Writeln('');
  692. Write('<Press Enter> [ ]'#8#8);
  693. Repeat until readkey = #13;
  694. Fclr;
  695. End;
  696.  
  697. begin {main program}
  698. (***********************************************************************)
  699.  Calibrate_Delay;
  700.  Delay(0);
  701.  PlayAnother := True;
  702.  
  703. Repeat
  704.  randomize;
  705.  NumEnemy := Random(16)+15;
  706.  Dead := False;
  707.  Score := 0;
  708.  Turn := 0;
  709.  Fclr;
  710.  SayHi;
  711.  HideCursor;
  712.  ClearKeyBoard;
  713.  Energy := StartingEnergy;
  714.  ShieldOn := False;
  715.  StatInit;
  716.  UpDateShields;
  717. (***********************************************************************)
  718.  
  719.  Status('Welcome to SNAiL ViSiON v'+version+' ...',True,False);
  720.  
  721.  Playgame;
  722.  
  723.  
  724. (***********************************************************************)
  725.  ShowCursor;
  726.  FCLR; {Not only clears the screen, but resets some things as well}
  727.  Writeln('Score: ',Score);
  728.  Write('Play again? (Y/n)');
  729.  Repeat
  730.  Ch := UpCase(Readkey);
  731.  Until (Ch = 'Y') or (CH = 'N');
  732.  If Ch = 'N' then playanother := False;
  733.  Until not PlayAnother;
  734.  Fclr;
  735. (***********************************************************************)
  736. end.
  737.  
  738. :::